#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
void fork_example1(void);
void fork_example2(void);
void fork_example3(void);
void fork_example4(void);
void fork_example5(void);
int main(void)
{
	fork_example5();
	return 0;
}
/**
 * 如何创建子进程
 * */
void fork_example1(void)
{
	int pid = fork();
	if(pid == -1)
	{
		printf("fork error\n");
	}
	// 根据fork的返回值判断是父进程还是子进程
	if(pid > 0)
	{
		// 父进程睡眠下，如果父进程在子进程结束之前结束，子进程ppid就为1
		sleep(1);
		printf("I am parent process,my pid is %d,my ppid is %d\n",getpid(),getppid());
	}
	else
	{
		printf("I am child process,my pid is %d,my ppid is %d\n",getpid(),getppid());
	}
}
/**
 * 父子进程哪个先运行由系统调度
 **/
void fork_example2(void)
{
	int pid = fork(),l = 10;
	if(pid == 0)
	{
		for(int i = 0;i < l;i++)
		{
			sleep(1);
			printf("parent pid => %d,ppid => %d;count => %d\n",getpid(),getppid(),i);
		}
	}
	else
	{
		for(int i = 0;i < l;i++)
		{
			sleep(1);
			printf("child pid => %d,ppid => %d;count => %d\n",getpid(),getppid(),i);
		}
	}
}
int a = 1;
/**
 * 子进程和父进程的虚拟地址是一样的，下面的打印可以看出，但是物理地址是不一样的
 * */
void fork_example3(void)
{
	int b = 2;
	int pid = fork();
	if(pid > 0)
	{
		printf("&a = %p;&b = %p",&a,&b);
	}
	else if(pid == 0)
	{
		printf("&a = %p;&b = %p",&a,&b);
	}
}
/**
 * io
 * */
void fork_example4(void)
{
	FILE* f1 = fopen("f1.txt","w+");
	int f2 = open("f2.txt",O_CREAT | O_WRONLY);
	// c标准函数写，这里的start在文件里面会写入两次，因为子进程会把标准的id的缓存也复制一边，最后结束时，就会写入两次
	fprintf(f1,"start\n");
	// 系统函数写
	write(f2,"start\n",6);
	int pid = fork();
	if(pid > 0)
	{
		// c标准函数写
		fprintf(f1,"parent end\n");
		// 系统函数写
		write(f2,"parent end\n",11);
	}
	else if(pid == 0)
	{
		// c标准函数写
		fprintf(f1,"child end\n");
		// 系统函数写
		write(f2,"child end\n",10);
	}
	fclose(f1);
	close(f2);
}
void fork_example5(void)
{
	int f = open("a.txt",O_WRONLY | O_CREAT);
	int pid = fork();
	if(pid > 0)
	{
		// 主进程调整位置，子进程写入
		lseek(f,0,SEEK_END);
	}
	else
	{
		sleep(3);
		// f是主进程f的复制，所以主进程使用lseek对子进程也是有效的
		write(f,"write",5);
	}
	close(f);
}
